/************************************************************/
/* 		MINIX IPC FUNCTIONS					*/
/* start CONTROL and IPC channels and bind to molkernel	*/ 
/* Emulates MINIX send, receive, sendrec, notify		*/
/* The messages are encapsulated on MOL messages		*/
/************************************************************/

#define _GNU_SOURCE 
#include <stdio.h>
#include <stdint.h> 
#include <dlfcn.h> 
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/*---------------------- MINIX HEADERS ---------------------------*/
#include "../../kernel/ipc.h"

/*---------------------- MOL HEADERS ---------------------------*/
#define MOLDBG 1
#include "../include/mol/molminix.h"
#include "../include/mol/mollib.h"
#include "../include/mol/molipc.h"

/*---------- GLOBAL data structure for the process -----*/


/************************************************************/
/* 		MINIX IPC FUNCTIONS					*/
/************************************************************/

/*----------------------------------------------------------*/
/*			mnx_send				*/
/*----------------------------------------------------------*/
int mnx_send(int dest, message *m_ptr, mol_proc_t  *mpp)
{
	int rcode;

	/* Send a SEND request to MOLKERNEL */
	mpp->sipc.molmsg.code = SEND;
	mpp->sipc.molmsg.spid = mpp->p_pid;
	mpp->sipc.molmsg.seq  = mpp->pseq++;
	mpp->sipc.molmsg.p_nr = mpp->p_nr; 
	mpp->sipc.molmsg.p_endpoint = mpp->p_endpoint; 
	mpp->sipc.molmsg.srcdst = dest;
	memcpy(&mpp->sipc.molmsg.mnxmsg, m_ptr, sizeof(message));
OLDEBUG("code=%X spid=%d seq=%ld p_nr=%d p_enpoint=%d m_source=%d srcdst=%d\n",
                mpp->sipc.molmsg.code,
                mpp->sipc.molmsg.spid,
                mpp->sipc.molmsg.seq,
                mpp->sipc.molmsg.p_nr,
                mpp->sipc.molmsg.p_endpoint,
                mpp->sipc.molmsg.mnxmsg.m_source,
                mpp->sipc.molmsg.srcdst);
	rcode = ipc_send(&mpp->sipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n", rcode);

	/* Wait for Reply from MOLKERNEL */
	rcode = ipc_rcv(&mpp->ripc);
	if( rcode != OK)
		MOLERROR("ipc_rcv rcode=%X\n", rcode);

	if( mpp->ripc.molmsg.code != (SEND | ACKNOWLEDGE))
		{
		MOLERROR("code=%X\n",mpp->ripc.molmsg.code);
		return(mpp->ripc.molmsg.code);
		}

OLDEBUG("code=%X \n",mpp->ripc.molmsg.code);
	return(OK);
}

/*----------------------------------------------------------*/
/*			mnx_receive						*/
/*----------------------------------------------------------*/
int mnx_receive(int src, message *m_ptr, mol_proc_t  *mpp)
{
	int rcode;

	/* Send a RECEIVE request to MOLKERNEL */
	mpp->sipc.molmsg.code = RECEIVE;
	mpp->sipc.molmsg.spid = mpp->p_pid;
	mpp->sipc.molmsg.seq  = mpp->pseq++;
	mpp->sipc.molmsg.p_nr = mpp->p_nr; 
	mpp->sipc.molmsg.p_endpoint = mpp->p_endpoint;
	mpp->sipc.molmsg.srcdst = src;
OLDEBUG("code=%X spid=%d seq=%ld p_nr=%d m_source=%d srcdst=%d\n",
                mpp->sipc.molmsg.code,
                mpp->sipc.molmsg.spid,
                mpp->sipc.molmsg.seq,
                mpp->sipc.molmsg.p_nr,
                mpp->sipc.molmsg.mnxmsg.m_source,
                mpp->sipc.molmsg.srcdst);
	rcode = ipc_send(&mpp->sipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n", rcode);

	/* Wait for Reply from MOLKERNEL */
	rcode = ipc_rcv(&mpp->ripc);
	if( rcode != OK)
		MOLERROR("ipc_recv rcode=%X\n", rcode);

	if( mpp->ripc.molmsg.code != (RECEIVE | ACKNOWLEDGE))
		{
		MOLERROR("code=%X\n",mpp->ripc.molmsg.code);
		return(mpp->ripc.molmsg.code);
		}
	memcpy(m_ptr, &mpp->ripc.molmsg.mnxmsg, sizeof(message));
OLDEBUG("code=%X\n",mpp->ripc.molmsg.code);
	return(OK);
}

/*----------------------------------------------------------*/
/*			mnx_sendrec					*/
/*----------------------------------------------------------*/
int mnx_sendrec(int srcdst, message *m_ptr, mol_proc_t  *mpp)
{
	int rcode;

	/* Send a SENDREC request to MOLKERNEL */
	mpp->sipc.molmsg.code = SENDREC;
	mpp->sipc.molmsg.spid = mpp->p_pid;
	mpp->sipc.molmsg.seq  = mpp->pseq++;
	mpp->sipc.molmsg.p_nr = mpp->p_nr; 
	mpp->sipc.molmsg.p_endpoint = mpp->p_endpoint;
	mpp->sipc.molmsg.srcdst = srcdst;
 	memcpy(&mpp->sipc.molmsg.mnxmsg, m_ptr, sizeof(message));
OLDEBUG("code=%X spid=%d seq=%ld p_nr=%d p_endpoint=%d m_source=%d srcdst=%d\n",
                mpp->sipc.molmsg.code,
                mpp->sipc.molmsg.spid,
                mpp->sipc.molmsg.seq,
                mpp->sipc.molmsg.p_nr,
                mpp->sipc.molmsg.p_endpoint,
                mpp->sipc.molmsg.mnxmsg.m_source,
                mpp->sipc.molmsg.srcdst);
	rcode = ipc_send(&mpp->sipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n", rcode);

	/* Wait for Reply from MOLKERNEL */
	rcode = ipc_rcv(&mpp->ripc);
	if( rcode != OK)
		MOLERROR("ipc_rcv rcode=%X\n", rcode);

	memcpy(m_ptr, &mpp->ripc.molmsg.mnxmsg, sizeof(message));
	if( mpp->ripc.molmsg.code == (SENDREC | ACKNOWLEDGE))
		{
		MOLERROR("code=%X\n",mpp->ripc.molmsg.code);
		return(mpp->ripc.molmsg.code);
		}

OLDEBUG("code=%X\n",mpp->ripc.molmsg.code);
	return(OK);
}

/*----------------------------------------------------------*/
/*			mnx_notify						*/
/*----------------------------------------------------------*/
int mnx_notify(int dest, message *m_ptr ,mol_proc_t  *mpp)
{
	int rcode;

	/* Send a SEND request to MOLKERNEL */
	mpp->sipc.molmsg.code = NOTIFY;
	mpp->sipc.molmsg.spid = mpp->p_pid;
	mpp->sipc.molmsg.seq  = mpp->pseq++;
	mpp->sipc.molmsg.p_nr = mpp->p_nr; 
	mpp->sipc.molmsg.p_endpoint = mpp->p_endpoint; 
	mpp->sipc.molmsg.srcdst = dest;
	memcpy(&mpp->sipc.molmsg.mnxmsg, m_ptr, sizeof(message));
OLDEBUG("code=%X spid=%d seq=%ld p_nr=%d p_enpoint=%d m_source=%d srcdst=%d\n",
                mpp->sipc.molmsg.code,
                mpp->sipc.molmsg.spid,
                mpp->sipc.molmsg.seq,
                mpp->sipc.molmsg.p_nr,
                mpp->sipc.molmsg.p_endpoint,
                mpp->sipc.molmsg.mnxmsg.m_source,
                mpp->sipc.molmsg.srcdst);
	rcode = ipc_send(&mpp->sipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n", rcode);

	return(OK);
}

/*----------------------------------------------------------*/
/*			mnx_bind						*/
/* Bind the process on  MOLKERNEL					*/
/* Send it's LINUX PID to MOLKERNEL (in .srcdst field)		*/
/* Waits for MINIX endpoint from MOLKERNEL	(in .code field)	*/
/*----------------------------------------------------------*/
int mnx_bind(mol_proc_t  *mpp)
{
	int rcode;

	/* Send a  BIND request to MOLKERNEL */
	mpp->kipc.molmsg.code = BIND;
	mpp->kipc.molmsg.spid = mpp->p_pid;
	mpp->kipc.molmsg.seq  = 0;
	mpp->kipc.molmsg.p_nr = 0;
	mpp->kipc.molmsg.p_endpoint = 0;
	mpp->kipc.molmsg.srcdst = 0;
	strncpy((char*)&mpp->kipc.molmsg.mnxmsg.m_u.m_m3.m3ca1,(char*)&mpp->p_name,P_NAME_LEN);
OLDEBUG("code=%X spid=%d m3ca1=%s \n",
	BIND,
	mpp->p_pid,
	mpp->p_name);

	rcode = ipc_send(&mpp->kipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n",rcode);

	/* Wait for Reply from MOLKERNEL */
	rcode = ipc_rcv(&mpp->kipc);
	if( rcode != OK)
		MOLERROR("ipc_rcv rcode=%X\n",rcode);

	if(!(mpp->kipc.molmsg.code & (BIND | ACKNOWLEDGE)))
		{
		MOLERROR("code=%X\n",mpp->kipc.molmsg.code);
		return(mpp->kipc.molmsg.code);
		}

	mpp->p_nr 			= mpp->kipc.molmsg.p_nr;
	mpp->p_endpoint 	= mpp->kipc.molmsg.p_endpoint;
	mpp->pseq = mpp->kseq = 1;	/* initialize sequence numbers */

OLDEBUG("code=%X p_nr=%d p_endpoint=%d\n",
		mpp->kipc.molmsg.code,
		mpp->kipc.molmsg.p_nr,
		mpp->kipc.molmsg.p_endpoint);
	
	/* Send a  BIND request to IPC SERVER */
	mpp->sipc.molmsg.code = BIND;
	mpp->sipc.molmsg.spid = mpp->p_pid;
	mpp->sipc.molmsg.p_nr = mpp->p_nr;
	mpp->sipc.molmsg.seq  = mpp->pseq++;
	mpp->sipc.molmsg.p_endpoint = mpp->p_endpoint;
	strncpy((char*)&mpp->sipc.molmsg.mnxmsg.m_u.m_m3.m3ca1,(char*)&mpp->p_name,P_NAME_LEN);
	rcode = ipc_send(&mpp->sipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n",rcode);
	
	/* Wait for Reply from IPCSERVER */
	rcode = ipc_rcv(&mpp->ripc);
	if( rcode != OK)
		MOLERROR("ipc_rcv rcode=%X\n",rcode);
		
	if(!(mpp->ripc.molmsg.code & (BIND | ACKNOWLEDGE)))
		{
		MOLERROR("code=%X\n",mpp->ripc.molmsg.code);
		return(mpp->ripc.molmsg.code);
		}
		
	return(OK);
}

/*----------------------------------------------------------*/
/*			mnx_unbind			*/
/* Undbinds from MOLKERNEL				*/
/*----------------------------------------------------------*/
int mnx_unbind(mol_proc_t  *mpp)
{
	int rcode;
OLDEBUG("\n");

	/* Send a UNBIND request to MOLKERNEL */
	mpp->kipc.molmsg.code = UNBIND;
	mpp->kipc.molmsg.spid = mpp->p_pid;
	mpp->kipc.molmsg.seq  = mpp->pseq++;
	mpp->kipc.molmsg.p_nr = mpp->p_nr; 
	mpp->kipc.molmsg.p_endpoint = mpp->p_endpoint;	
	mpp->kipc.molmsg.srcdst = 0;
	rcode = ipc_send(&mpp->kipc);
	if( rcode != OK)
		MOLERROR("ipc_send rcode=%X\n",rcode);

	/* Wait for Reply from MOLKERNEL */
	rcode = ipc_rcv(&mpp->kipc);
	if( rcode != OK)
		MOLERROR("ipc_rcv rcode=%X\n",rcode);

	if( mpp->kipc.molmsg.code != (UNBIND | ACKNOWLEDGE))
		MOLERROR("code=%X\n",mpp->kipc.molmsg.code);

OLDEBUG("code=%X p_nr=%d p_endpoint=%d\n",
		mpp->kipc.molmsg.code,
		mpp->kipc.molmsg.p_nr,
		mpp->kipc.molmsg.p_endpoint);

return(OK);
}


